home *** CD-ROM | disk | FTP | other *** search
/ Info-Mac 4 / Info_Mac IV CD-ROM (Pacific HiTech Inc.)(August 1994).iso / Development / Source / Telnet 2.6.1d1 4⁄26⁄94 Folder / source / test / Audit.h < prev   
Text File  |  1993-09-17  |  19KB  |  505 lines

  1. /*                                        Audit.h                                    */
  2. /*
  3.  * Audit.h
  4.  * Copyright © 1992-93 Apple Computer Inc. All Rights Reserved.
  5.  * Programmed by Martin Minow,
  6.  *    Internet:    minow@apple.com
  7.  *    AppleLink:    MINOW
  8.  * Version of January 14, 1993
  9.  *
  10.  * Edit History
  11.  *    93.01.09 MM        First public release
  12.  *    93.01.14 MM        Think and MPW generate different record sizes; a disaster if
  13.  *                    you create an Audit Record under Think and call Audit compiled
  14.  *                    under MPW. Also added a test for record sizes and included
  15.  *                    record size information in the AuditRecord.
  16.  *    93.07.09 MM        Conversion to Think C 6.0, text reformatted for standard
  17.  *                    page layout, no substantive changes 
  18.  *    93.08.14 MM        Added "logicalRAMSize to the AuditRecord. This protects
  19.  *                    Audit (somewhat) against bad data forcing address errors.
  20.  *
  21.  * This file contains the unique definitions used for driver and code-segment
  22.  * logging.
  23.  *
  24.  * Note: because Pascal does not support variable-length calling sequences,
  25.  * the functions are C-format only.
  26.  */
  27. #ifndef __Audit__
  28. #define __Audit__
  29.  
  30. #include <stdarg.h>
  31. #include <OSUtils.h>
  32. #include <Processes.h>
  33.  
  34. /*
  35.  * To create an audit record, a driver, application, or other code segment calls
  36.  * InitAudit(). This is the only function that accesses the memory manager. The
  37.  * audit record is created on the System Heap.
  38.  *
  39.  * To obtain a reference to an audit record, a code segment calls GetAuditPtr().
  40.  * This may be called at any time.
  41.  *
  42.  * Both InitAudit and GetAuditPtr are moderately inefficient (they call Gestalt()).
  43.  * Thus, a driver (etc.) should store the value in a private variable. For example,
  44.  * a driver would typically store the value in a variable in its driver control
  45.  * block. The Audit Record never moves in memory.
  46.  *
  47.  * Once an audit area has been created for a particular Gestalt selector,
  48.  * it persists in its current form until the computer is re-booted.
  49.  *
  50.  * The display application processes log entries as follows. Note
  51.  * that all functions may be safely called with a NULL auditPtr:
  52.  *
  53.  *        gAuditPtr = GetAuditPtr(kMyAuditSelector);
  54.  *        GetCurrentProcess(&gOldLogProcess);
  55.  *        WakeUpAudit(gAuditPtr, &gOldProcess);
  56.  *        wasLogging = EnableAudit(gAuditPtr, TRUE);
  57.  *        while (gQuitNow == FALSE) {
  58.  *            ProcessOneEvent();
  59.  *            for (i = 0; i < 100; i++) {
  60.  *                if (ReadAudit(gAuditPtr, &missed, &logEntry) == FALSE)
  61.  *                    break;
  62.  *                else {
  63.  *                    Str255        timeText, dataText;
  64.  *
  65.  *                    FormatAuditEntryTimestamp(gAuditPtr, &logEntry, timeText);
  66.  *                    FormatAuditEntryData(&ENTRY, dataText);
  67.  *                    DisplayString(timeText);
  68.  *                    DisplayString(dataText);
  69.  *                }
  70.  *            }
  71.  *        }
  72.  *        EnableAudit(gAuditPtr, wasLogging);
  73.  *        WakeUpCurrentProcess(&gOldLogProcess);
  74.  *        ExitToShell();
  75.  */
  76.  
  77. /*
  78.  * Each audit record entry contains the following information:
  79.  *        tickCount        The Ticks value at the time the data was collected.
  80.  *        lostData        The number of audit records that were not stored before
  81.  *                        this one because Audit was called when there were no free
  82.  *                        records available.
  83.  *        idCode            A longword that uniquely identifies the log entry (i.e.,
  84.  *                        who logged it). This is provided by the Audit caller.
  85.  *        format            A longword that describes the format of the log data.
  86.  *        data[8]            eight longwords that contain the entry-unique information.
  87.  *                        The actual conte is defined by the format longword.
  88.  * TickCount and lostData are maintained by the Audit library, while the other
  89.  * parameters are copied from the Audit parameters. Each entry is time-stamped by
  90.  * the following algorithm:
  91.  *        elapsedTicks = RECORD.tickCount - LOG.ticksAtStart;
  92.  *        SecsToDate(
  93.  *            LOG.timeAtStart + elapsedTicks / 60,
  94.  *            &logEntryDateString
  95.  *        );
  96.  *        printf(, ..., date.second, elapsedTicks % 60);
  97.  * AuditRead returns a copy of the current audit record. See AuditEntryFormat.c
  98.  * and AuditDCMD.c for record formatting examples. Note that, because of the way
  99.  * formatting data is stored, changing the size of data[] is very difficult --
  100.  * and not recommended.
  101.  */
  102. typedef struct AuditEntry {
  103.     unsigned long            tickCount;    /* TickCount() at Audit call            */
  104.     unsigned long            lostData;    /* Missing records before this one        */
  105.     OSType                    idCode;        /* Why are we logging -- set by caller    */
  106.     unsigned long            format;        /* Format of the data (see below)        */
  107.     unsigned long            data[8];    /* The data itself                        */
  108. } AuditEntry, *AuditEntryPtr;
  109. /*
  110.  * Hand-compute the size to make sure that compiler quirks don't mess us up.
  111.  * We check that kSizeofAuditEntry equals sizeof (AuditEntry). The ANSI C
  112.  * Standard does not permit "sizeof" in a #define statement.
  113.  */
  114. #define kSizeofAuditEntry ((4 * 4) + (4 * 8))
  115.  
  116.  
  117. /*
  118.  * AuditQueueEntry is a private structure (only Audit.c and AuditDCMD.c reference
  119.  * it). It contains the Audit entry record and a queue element pointer that
  120.  * connects this record with other records in the free or to-be-processed queues.
  121.  */
  122. typedef struct AuditQueueEntry {
  123.     QElemPtr                qLink;        /* Queue linkage        */
  124.     AuditEntry                theEntry;    /* User's data area        */
  125. } AuditQueueEntry, *AuditQueueEntryPtr;
  126. #define kSizeofAuditQueueEntry (kSizeofAuditEntry + 4)
  127.  
  128. /*
  129.  * The audit record contains a fixed header with the following information:
  130.  *
  131.  *        lowVersion        The earliest version of the AuditRecord that the library
  132.  *                        that created the record understands.
  133.  *        highVersion        The latest version of the AuditRecord that the library
  134.  *                        that created the record understands.
  135.  *        recordSize        This longword encodes the size of the AuditRecord and
  136.  *                        AuditQueueEntry to ensure that compiler alignment
  137.  *                        considerations do not cause code to crash.
  138.  *        free.queue        An O.S. queue with available log records.
  139.  *        data.queue        An O.S. queue with busy log records.
  140.  *        lostData        The number of records not logged. This is cleared whenever
  141.  *                        Audit successfully stores a caller's request.
  142.  *        PSN                The ProcessSerialNumber of the process to awaken when
  143.  *                        something is logged.
  144.  *        refNum            A longword that is available for your use.
  145.  *        logEnabled        TRUE if logging.
  146.  *        timeAtStart        GetDateTime() when the log was created.
  147.  *        ticksAtStart    TickCount() when the log was created.
  148.  * User software accesses an audit record by calling Audit functions. This is
  149.  * necessary so that the record can be accessed by interrupt-level routines
  150.  * without risk of obtaining inconsistent data.
  151.  *
  152.  * Note: the QHdr structure is not longword aligned. Some compilers add an extra
  153.  * 16-bit word padding. If an AuditRecord is created by code generated by one
  154.  * compiler, and accessed by code generated by the other compiler, disaster ensues.
  155.  * To prevent this, the QHdr structures are encapsulated in a dummy structure that
  156.  * is longword aligned. This is ugly, but the alternative is uglier.
  157.  */
  158. typedef struct AuditRecord {
  159.     union {
  160.       void                *unusedLong;    /* Force longword align    */
  161.       struct {
  162.         unsigned short    low;            /* Earliest lib version    */
  163.         unsigned short    high;            /* Latest lib version    */
  164.       } u;
  165.     } version;
  166.     unsigned long        recordSize;        /* Compiler check        */
  167.     unsigned long        lostData;        /* Missed log counter    */
  168.     void                *refNum;        /* User-controlled long    */
  169.     unsigned long        flags;            /* Logging & lost data    */
  170.     unsigned long        timeAtStart;    /* GetDateTime()        */
  171.     unsigned long        ticksAtStart;    /* TickCount()            */
  172.     ProcessSerialNumber    PSN;            /* Wakeup this process    */
  173.     unsigned long        logicalRAMSize;    /* From Gestalt            */
  174.     union {
  175.         QHdr            queue;            /* Free queue header    */
  176.         long            unused[
  177.             (sizeof (QHdr) + (sizeof (long) - 1)) / sizeof (long)
  178.         ];
  179.     } free;
  180.         union {
  181.         QHdr            queue;            /* Data queue header    */
  182.         long            unused[
  183.             (sizeof (QHdr) + (sizeof (long) - 1)) / sizeof (long)
  184.         ];
  185.     } data;
  186.     AuditQueueEntry        entries[1];        /* Entries stored here    */
  187. } AuditRecord, *AuditPtr;
  188. #define kSizeofAuditRecord (                                        \
  189.         + (8 * 4)                    /* Various longwords        */    \
  190.         + (12 * 2)                    /* sizeof QHdr's            */    \
  191.         + sizeof (ProcessSerialNumber)                                \
  192.         + kSizeofAuditQueueEntry                                    \
  193.     )
  194. #define kAuditRecordSize ((unsigned long) (                            \
  195.         ((sizeof (AuditRecord) - sizeof (AuditQueueEntry)) << 16L)    \
  196.         | sizeof (AuditQueueEntry)                                    \
  197.     ))
  198.  
  199. /*
  200.  * Values for the flags variable in the AuditRecord. These are private to the
  201.  * Audit library and dcmd display routine.
  202.  */
  203. #define kAuditEnabledMask        1
  204. #define kAuditPreserveFirstMask    2
  205.  
  206. /*
  207.  * These flags control data formatting. Note: because data is passed using
  208.  * variable-length argument list conventions and we want the code to work
  209.  * compatibly on both Think and MPW, all numeric parameters must be passed as
  210.  * "long" or "unsigned long." For example, to pass an OSErr code, do
  211.  *        Audit(
  212.  *            auditPtr,
  213.  *            'fubr',
  214.  *            AuditFormat1(kAuditFormatSigned),
  215.  *            (signed long) statusCode
  216.  *        );
  217.  */
  218. enum {
  219.     /*
  220.      * Parameters to the AuditFormat macro.
  221.      */
  222.     kAuditFormatSigned            = 0,        /* Signed long            */
  223.     kAuditFormatUnsigned        = 1,        /* Unsigned (decimal)    */
  224.     kAuditFormatHex                = 2,        /* Unsigned (hex/char)    */
  225.     kAuditFormatAddress            = 3,        /* Unsigned hex only    */
  226.     kAuditFormatReserved        = 4,        /* Unused                */
  227.     kAuditFormatLocation        = 5,        /* Location (last fmt)    */
  228.     kAuditFormatString            = 6,        /* String (last format)    */
  229.     kAuditFormatEnd                = 7,        /* End signal (no data)    */
  230.     /*
  231.      * kAuditFormatShift must be large enough to shift all format codes. All data
  232.      * format codes must fit into a single longword.
  233.      */
  234.     kAuditFormatShift        = 3,
  235.     kAuditFormatMask        = (1 << kAuditFormatShift) - 1
  236. };
  237.  
  238. /*
  239.  * The AuditFormat macro stores the format word.
  240.  */
  241. #define AuditFormat(f0, f1, f2, f3, f4, f5, f6, f7)    \
  242.     (  (f0)                                            \
  243.      | ((f1) << (kAuditFormatShift * 1))            \
  244.      | ((f2) << (kAuditFormatShift * 2))            \
  245.      | ((f3) << (kAuditFormatShift * 3))            \
  246.      | ((f4) << (kAuditFormatShift * 4))            \
  247.      | ((f5) << (kAuditFormatShift * 5))            \
  248.      | ((f6) << (kAuditFormatShift * 6))            \
  249.      | ((f7) << (kAuditFormatShift * 7))            \
  250.      | (kAuditFormatEnd << (kAuditFormatShift * 8))    \
  251.     )
  252. #define AuditFormat1(f0)                                                    \
  253.     AuditFormat(                                                            \
  254.         (f0),          kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd,    \
  255.         kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd    \
  256.     )
  257. #define AuditFormat2(f0, f1)                                                \
  258.     AuditFormat(                                                            \
  259.         (f0),          (f1),          kAuditFormatEnd, kAuditFormatEnd,        \
  260.         kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd    \
  261.     )
  262. #define AuditFormat3(f0, f1, f2)                                            \
  263.     AuditFormat(                                                            \
  264.         (f0),          (f1),          (f2),          kAuditFormatEnd,        \
  265.         kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd    \
  266.     )
  267. #define AuditFormat4(f0, f1, f2, f3)                                        \
  268.     AuditFormat(                                                            \
  269.         (f0),          (f1),          (f2),          (f3),                    \
  270.         kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd    \
  271.     )
  272. #define AuditFormat5(f0, f1, f2, f3, f4)                                    \
  273.     AuditFormat(                                                            \
  274.         (f0),          (f1),          (f2),          (f3),                    \
  275.         (f4),          kAuditFormatEnd, kAuditFormatEnd, kAuditFormatEnd    \
  276.     )
  277. #define AuditFormat6(f0, f1, f2, f3, f4, f5)                                \
  278.     AuditFormat(                                                            \
  279.         (f0),          (f1),          (f2),          (f3),                    \
  280.         (f4),          (f5),          kAuditFormatEnd, kAuditFormatEnd        \
  281.     )
  282. #define AuditFormat7(f0, f1, f2, f3, f4, f5, f6)                            \
  283.     AuditFormat(                                                            \
  284.         (f0),          (f1),          (f2),          (f3),                    \
  285.         (f4),          (f5),          (f6),          kAuditFormatEnd        \
  286.     )
  287. #define AuditFormat8(f0, f1, f2, f3, f4, f5, f6, f7)                        \
  288.     AuditFormat(                                                            \
  289.         (f0),          (f1),          (f2),          (f3),                    \
  290.         (f4),          (f5),          (f6),          (f7)                    \
  291.     )
  292.  
  293. /*
  294.  * The driver or code segment calls the following functions to access audit
  295.  * records. InitAudit returns NULL if it couldn't create an audit record. It must
  296.  * be called when memory allocation is permitted (i.e. from an application, init,
  297.  * or a driver open routine).
  298.  *
  299.  * All functions that take an AuditPtr argument are "NULL-safe:" if called with a
  300.  * null parameter, they do nothing (gracefully).
  301.  *
  302.  *        gestaltSelector        Used to identify this audit record to the display
  303.  *                            application.
  304.  *        nEntries            The number of audit entries. Each audit entry consumes
  305.  *                            52 bytes of non-relocatable System Heap space.
  306.  *        initiallyEnabled    TRUE to start logging upon creation. The EnableAudit
  307.  *                            function allows modifying this parameter.
  308.  *        preserveFirst        If TRUE and the entry area fills, preserve the first
  309.  *                            nEntries, losing the newest entry. If FALSE and the
  310.  *                            entry area fills, delete the earliest entry, preserving
  311.  *                            the newest entry. The PreserveAudit function allows
  312.  *                            modifying this parameter.
  313.  * If some other program has already created an audit record with this
  314.  * gestaltSelector, the function returns a pointer to that log record. This is not
  315.  * necessarily an error. For example, it allows a driver to locate a log record
  316.  * that had been created by an init routine. If the init routine did not run,
  317.  * the driver will create the record. This may be useful for developers who are
  318.  * trying to track down obscure "happens only at the customer site" bugs.
  319.  */
  320. AuditPtr                    InitAudit(
  321.         OSType                    gestaltSelector,    /* Gestalt to create        */
  322.         unsigned short            nEntries,            /* Number of audit entries    */
  323.         Boolean                    initiallyEnabled,    /* Start auditing now?        */
  324.         Boolean                    preserveFirst        /* Save earlier entries?    */
  325.     );
  326.  
  327. /*
  328.  * This function writes an audit entry if auditing is enabled.
  329.  *
  330.  *        auditPtr            As returned by AuditInit. If NULL, nothing is logged.
  331.  *        idCode                A user-controlled value, by convention an OSType
  332.  *                            (4-byte character) that identifies this entry. The
  333.  *                            display application prints it. Note that, on the
  334.  *                            Macintosh, an OSType can be coerced from/to any
  335.  *                            longword scalar (such as an address) without loss of
  336.  *                            data. This may be useful for user-written display
  337.  *                            applications.
  338.  *        format                A longword that specifies the format of the remaining
  339.  *                            data. Use the value AuditFormat1(kAuditFormatString)
  340.  *                            if the only datum is a pascal string, otherwise, use
  341.  *                            the AuditFormat macro to create the value.
  342.  *        ...                    Additional data as needed. Note that all data must be
  343.  *                            specified as longwords (StringPtr, address, or long).
  344.  *                            Naturally short integers such as Booleans or OSErr
  345.  *                            codes must be explicitly cast to long. This is needed
  346.  *                            because of differences between Think C and MPW
  347.  *                            compilers.
  348.  */
  349. void                        Audit(
  350.         AuditPtr                auditPtr,    /* Audit Record Pointer                */
  351.         OSType                    idCode,        /* User-specified identifier        */
  352.         unsigned long            format,        /* Format bits                        */
  353.         ...                                    /* Additional data, if any            */
  354.     );
  355.  
  356. /*
  357.  * AuditString calls Audit with a single Pascal string argument
  358.  */
  359. #define AuditString(auditPtr, idCode, string) (            \
  360.         Audit(                                            \
  361.             (auditPtr),                                    \
  362.             (idCode),                                    \
  363.             AuditFormat1(kAuditFormatString),            \
  364.             string                                        \
  365.         )                                                \
  366.     )
  367.  
  368. /*
  369.  * AuditStatusString calls Audit with the status and string values.
  370.  */
  371. #define AuditStatusString(auditPtr, idCode, status, string) ( \
  372.         Audit(                                            \
  373.             (auditPtr),                                    \
  374.             (idCode),                                    \
  375.             AuditFormat2(kAuditFormatSigned, kAuditFormatString), \
  376.             (signed long) (status),                        \
  377.             string                                        \
  378.         )                                                \
  379.     )
  380. /*
  381.  * AuditStatusLocation calls Audit with the function location.
  382.  */
  383. #define AuditStatusLocation(auditPtr, idCode, status) (    \
  384.         Audit(                                            \
  385.             (auditPtr),                                    \
  386.             (idCode),                                    \
  387.             AuditFormat2(kAuditFormatSigned, kAuditFormatLocation), \
  388.             (signed long) (status)                        \
  389.         )                                                \
  390.     )
  391.  
  392. /*
  393.  * Return a pointer to the log area, or NULL if there is none. Note: this can be
  394.  * called at any time (even from a driver completion routine), so exception
  395.  * logging can take place (somewhat inefficiently) even if the AuditPtr is not
  396.  * stored permanently.
  397.  */
  398. AuditPtr                    GetAuditPtr(
  399.         OSType                    gestaltSelector
  400.     );
  401.  
  402. /*
  403.  * Awaken a specified process when data is stored in the audit record. Call by the
  404.  * following sequence:
  405.  *        GetCurrentProcess(&oldPSN);        // process to awaken
  406.  *        WakeUpAudit(auditPtr, &oldPSN);
  407.  *    The previous process is now stored in oldPSN)
  408.  *        ... display the log ...
  409.  *        WakeUpAudit(auditPtr, &oldPSN);    // restore old
  410.  *        ExitToShell();
  411.  * This is normally only called by the display application.
  412.  */
  413. void                        WakeUpAudit(
  414.         AuditPtr                auditPtr,
  415.         ProcessSerialNumber        *oldPSN
  416.     );
  417.  
  418. /*
  419.  * Enable/disable audit logging. Returns the old logging state.
  420.  */
  421. Boolean                        EnableAudit(
  422.         AuditPtr                auditPtr,
  423.         Boolean                    enableLogging
  424.     );
  425.  
  426. /*
  427.  * Return the value of the Audit enable flag. Returns FALSE if auditPtr is NULL or
  428.  * auditing is disabled.
  429.  */
  430. Boolean                        IsAuditEnabled(
  431.         AuditPtr                auditPtr
  432.     );
  433.  
  434. /*
  435.  * Set the preserveAudit flag. Returns the old flag value.
  436.  */
  437. Boolean                        PreserveAudit(
  438.         AuditPtr                auditPtr,
  439.         Boolean                    preserveFirst
  440.     );
  441.  
  442. /*
  443.  * Get the time that the log record was created. This is used to time-stamp log
  444.  * entries.
  445.  */
  446. void                        GetAuditStartTimes(
  447.         AuditPtr                auditPtr,
  448.         unsigned long            *timeAtStart,
  449.         unsigned long            *ticksAtStart
  450.     );
  451.  
  452. /*
  453.  * Read the next audit entry. This returns a copy of the entry, if one is
  454.  * available, and returns TRUE. This function manages all log queues. ReadAudit
  455.  * returns FALSE if no entry is available or auditPtr is NULL.
  456.  */
  457. Boolean                        ReadAudit(
  458.         AuditPtr                auditPtr,
  459.         AuditEntryPtr            thisLogEntry
  460.     );
  461.  
  462. /*
  463.  * Store a user-controlled reference value. This may be coerced to any scalar
  464.  * value (such as a memory pointer or longword). SetAuditRefNum returns the
  465.  * previous value of the refNum, or NULL if no value had been stored.
  466.  */
  467. void                        *SetAuditRefNum(
  468.         AuditPtr                auditPtr,
  469.         void                    *refNum
  470.     );
  471.  
  472. /*
  473.  * Return the current user-controlled reference value. This may be coerced to any
  474.  * scalar value (such as a memory pointer or longword). This returns zero if
  475.  * auditPtr is NULL or no value had been stored.
  476.  */
  477. void                        *GetAuditRefNum(
  478.         AuditPtr                auditPtr
  479.     );
  480.  
  481. /*
  482.  * This function is in AuditEntryFormat.c - it formats an entry into a single line
  483.  * that is stored in the result. Note: only the data is formatted: the timestamp
  484.  * is not processed.
  485.  */
  486. void                        FormatAuditEntryData(
  487.         register AuditEntryPtr    entryPtr,
  488.         StringPtr                result
  489.     );
  490.  
  491. /*
  492.  * This function is in AuditEntryFormat.c - it formats the timestamp into
  493.  * yyyy.mm.dd hh.mm.ss.msec format. Audit does not use the built-in date
  494.  * formatting routines.
  495.  */
  496. void                        FormatAuditEntryTimestamp(
  497.         register AuditPtr        auditPtr,
  498.         register AuditEntryPtr    entryPtr,
  499.         StringPtr                result
  500.     );
  501.  
  502.  
  503. #endif    /* __Audit__    */
  504.  
  505.